package com.smmisia.article.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smmisia.article.api.AuthService;
import com.smmisia.article.dto.request.FollowRequest;
import com.smmisia.article.dto.response.LikeFollowCountDTO;
import com.smmisia.article.dto.response.UserResDTO;
import com.smmisia.article.dto.response.UserSimpleInfoDTO;
import com.smmisia.article.entity.Concern;
import com.smmisia.article.entity.Follow;
import com.smmisia.article.entity.User;
import com.smmisia.article.entity.convetor.UserConvertor;
import com.smmisia.article.exception.customException;
import com.smmisia.article.listen.message.FollowMessage;
import com.smmisia.article.mapper.ConcernMapper;
import com.smmisia.article.mapper.FollowMapper;
import com.smmisia.article.mapper.UserMapper;
import com.smmisia.article.service.FollowService;
import com.smmisia.article.utils.BeanUtil;
import com.smmisia.common.Result.Result;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


@Service
@Slf4j
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow>
        implements FollowService {

    private static final String FOLLOWING = "following:user_id:";

    private static final String FOLLOWS = "follows:user_id:";

    private static final String FRIENDS = "friends:";

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private FollowMapper followMapper;

    @Autowired
    private ConcernMapper concernMapper;

    @Autowired
    private AuthService authService;

    @Autowired
    private StreamBridge streamBridge;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 获取好友列表
     */
    public Set<String> getFriends(String userId) {

        Set<String> friends = redisTemplate.opsForSet().members(FRIENDS + userId);
        if (friends != null && !friends.isEmpty()) {
            return friends;
        }

        // 缓存结果到好友集合
        if (friends != null && !friends.isEmpty()) {
            redisTemplate.opsForSet().add(FRIENDS + userId,
                    friends.toArray(new String[0]));
        }

        return friends != null ? friends : new HashSet<>();
    }

    /**
     * 更新好友关系
     */
    public void updateFriendship(Integer userId, Integer targetId) {
        // 检查是否互相关注
        Boolean isFollowing = redisTemplate.opsForSet()
                .isMember(FOLLOWING + userId, targetId);
        Boolean isFollowed = redisTemplate.opsForSet()
                .isMember(FOLLOWING + targetId, userId);

        if (Boolean.TRUE.equals(isFollowing) && Boolean.TRUE.equals(isFollowed)) {
            // 互相关注，添加好友关系
            redisTemplate.opsForSet().add(FRIENDS + userId, targetId);
            redisTemplate.opsForSet().add(FRIENDS + targetId, userId);
        } else {
            // 取消关注，删除好友关系
            redisTemplate.opsForSet().remove(FRIENDS + userId, targetId);
            redisTemplate.opsForSet().remove(FRIENDS + targetId, userId);
        }
    }


    @Override
    public Result<String> follow(FollowRequest followRequest) {
        String userId = (String) StpUtil.getLoginId();
        Integer targetId = followRequest.getId();

        if (userId.equals(targetId)) {
            throw new customException("不能关注自己");
        }

        User user = authService.info(targetId);
        if (user == null) {
            throw new customException("当前用户不存在");
        }

        Boolean isMember = redisTemplate.opsForSet().isMember(FOLLOWING + userId, targetId);

        FollowMessage message = new FollowMessage();
        message.setUserId(Integer.parseInt(userId));
        message.setTargetId(targetId);

        if (Boolean.TRUE.equals(isMember)) {
            // 取消关注逻辑
            boolean send = streamBridge.send("follows-out-0", "rocketmq",
                    MessageBuilder.withPayload(message)
                            .setHeader("TAGS", "follows")
                            .build());

            if (!send) {
                log.info("消息发送失败:" + message);
                throw new customException("取消关注失败");
            }
                redisTemplate.opsForSet().remove(FOLLOWING + userId, targetId);
                redisTemplate.opsForSet().remove(FOLLOWS + targetId, Integer.valueOf(userId));
                // 更新好友关系
                updateFriendship(Integer.valueOf(userId), targetId);
            return Result.ok("取消关注成功");

        } else {
            // 关注逻辑
            boolean send = streamBridge.send("following-out-0", "rocketmq",
                    MessageBuilder.withPayload(message)
                            .setHeader("TAGS", "following")
                            .build());

            if (!send) {
                log.info("消息发送失败:" + message);
                throw new customException("关注失败");
            }

//            Follow follow = followMapper.selectOne(
//                    Wrappers.<Follow>lambdaQuery()
//                            .eq(Follow::getUserId, userId)
//                            .eq(Follow::getFollowUserId, targetId));
//
//            if (follow == null) {
//                throw new customException("关注失败");
//            }

            // 直接执行Redis操作
            redisTemplate.opsForSet().add(FOLLOWING + userId, targetId);
            redisTemplate.opsForSet().add(FOLLOWS + targetId, Integer.valueOf(userId));
            // 更新好友关系
            updateFriendship(Integer.valueOf(userId), targetId);

            return Result.ok("关注成功");
        }
    }


    /**
     * 检查是否是好友
     */
    public boolean isFriend(String userId, String targetId) {
        return Boolean.TRUE.equals(redisTemplate.opsForSet()
                .isMember(FRIENDS + userId, targetId));
    }


    /**
     * 用户关注列表
     *
     * @return
     */
    @Override
    public Result<List<UserResDTO>> followList() {
        Integer userId = StpUtil.getLoginIdAsInt();
        List<UserResDTO> resDTOList = new ArrayList<>();
        followMapper.selectList(
                        Wrappers.lambdaQuery(Follow.class)
                                .eq(Follow::getUserId, userId))
                .stream()
                .map(Follow::getFollowUserId)
                .forEach(id -> {
                    User user = authService.info(id);
                    UserResDTO userResDTO = UserConvertor.INSTANCE.mapToUserResDTO(user);
                    resDTOList.add(userResDTO);
                });
        return Result.ok(resDTOList);
    }

    /**
     * 用户粉丝列表
     *
     * @return
     */
    @Override
    public Result<List<UserResDTO>> concernList() {
        Integer userId = StpUtil.getLoginIdAsInt();
        List<UserResDTO> resDTOList = new ArrayList<>();
        concernMapper.selectList(Wrappers.lambdaQuery(Concern.class)
                        .eq(Concern::getUserId, userId)).stream()
                .map(Concern::getConcernUserId)
                .forEach(id -> {
                    User user = authService.info(id);
                    UserResDTO userResDTO = UserConvertor.INSTANCE.mapToUserResDTO(user);
                    resDTOList.add(userResDTO);
                });
        return Result.ok(resDTOList);
    }

    @Override
    public Result<List<UserResDTO>> listFriend() {
        // 1.获取当前用户
        Integer userId = StpUtil.getLoginIdAsInt();
        Set members = getFriends(userId.toString());
        if (members.isEmpty()) {
            return Result.ok(null);
        }
        List<Integer> list = (List<Integer>) members.stream().collect(Collectors.toList());
        List<UserResDTO> res = new ArrayList<>();
        list.forEach(id -> {
            User user = authService.info(id);
            UserResDTO userResDTO = UserConvertor.INSTANCE.mapToUserResDTO(user);
            res.add(userResDTO);
        });
        return Result.ok(res);
    }

    @Override
    public Result<Boolean> isFollow(Integer id) {
        if (id == null) {
            return Result.fail("id不能为空");
        }
        if (redisTemplate.opsForSet().isMember(FOLLOWING + StpUtil.getLoginIdAsInt(), id)) {
            return Result.ok(true);
        }
        return Result.ok(false);
    }


    /**
     * 获取用户关注数量，粉丝数量
     *
     * @param id
     * @return
     */
    public LikeFollowCountDTO count(Integer id) {
        LikeFollowCountDTO likeFollowCountDTO = new LikeFollowCountDTO();
        Long followCount = redisTemplate.opsForSet().size(FOLLOWING + id);
        Long concernCount = redisTemplate.opsForSet().size(FOLLOWS + id);
        if (followCount == null) {
            Integer followCounts = followMapper.selectFollow(id);
            likeFollowCountDTO.setFollowCount(followCounts);
        }
        if (concernCount == null) {
            Integer concernCounts = concernMapper.selectFollow(id);
            likeFollowCountDTO.setFollowCount(concernCounts);
        }
        likeFollowCountDTO.setFollowCount(followCount.intValue());
        likeFollowCountDTO.setConcernCount(concernCount.intValue());
        return likeFollowCountDTO;
    }

}




